package cn.lichenes.service.impl;

import cn.lichenes.entity.*;
import cn.lichenes.repository.*;
import cn.lichenes.service.PhoneService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class PhoneServiceImpl implements PhoneService{

    @Autowired
    private PhoneRepository phoneRepository;
    @Autowired
    private BrandRepository brandRepository;
    @Autowired
    private PictureRepository pictureRepository;
    @Autowired
    private EvaluateRepository evaluateRepository;

    public Map<String, Object> findAll(Integer page, String keyword) {
        PageRequest pageRequest = PageRequest.of(page-1, 6);
        Specification<Phone> specification = new Specification<Phone>() {
            public Predicate toPredicate(Root<Phone> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                if (keyword != "" || keyword != null) {
                    Predicate predicate = criteriaBuilder.or(criteriaBuilder.equal(root.get("phoneBrand").get("pbName").as(String.class), keyword), criteriaBuilder.like(root.get("pName").as(java.lang.String.class), "%" + keyword + "%"));
                    return predicate;
                }
                return null;
            }
        };
        Page<Phone> phonePage = phoneRepository.findAll(specification,pageRequest);
        List<PhoneBrand> brands = brandRepository.findAll();
        Map<String,Object> map = new HashMap<>();
        map.put("brands",brands);
        map.put("phones",phonePage.getContent());
        map.put("currentPage",page);
        map.put("totalPages",phonePage.getTotalPages());
        return map;
    }

    @Transactional
    public boolean updatePhone(Integer id, double price, Integer residue, String description, String status) {
        Phone phone = phoneRepository.findById(id).get();
        phone.setpPrice(price);
        phone.setpResidue(residue);
        phone.setpDescription(description);
        Integer pStatus = "上架".equals(status) ? 1:0;
        phone.setpStatus(pStatus);
        phoneRepository.save(phone);
        return true;
    }

    @Transactional
    public boolean save(Phone phone, String brand, List<PhonePicture> pictures) {
        PhoneBrand phoneBrand = brandRepository.findByPbName(brand);
        phone.setPhoneBrand(phoneBrand);
        phone.setPhonePictures(pictures);
        pictureRepository.saveAll(pictures);
        phoneRepository.save(phone);
        return true;
    }

    public Map<String, Object> getAll() {
        Map<String,Object> map = new HashMap<>();
        PageRequest pageRequest = PageRequest.of(0, 6);
        List<PhoneBrand> brands = brandRepository.findAll();
        map.put("brands",brands);
        for (PhoneBrand brand : brands) {
            List<Phone> phones = phoneRepository.findByPhoneBrandPbId(brand.getPbId(),pageRequest);
            switch (brand.getPbId()){
                case 1:
                    map.put("huawei",phones);
                    break;
                case 2:
                    map.put("mi",phones);
                    break;
                case 3:
                    map.put("apple",phones);
                    break;
                case 4:
                    map.put("oneplus",phones);
                    break;
                case 5:
                    map.put("vivo",phones);
                    break;
                default:
                    map.put("oppo",phones);
                    break;
            }

        }
        return map;
    }

    public Page<Phone> getPhoneByPrice(String brand, Double price, Integer page) {
        PageRequest pageRequest = PageRequest.of(page - 1, 6, Sort.by(Sort.Direction.DESC,"pSales"));
        Specification<Phone> specification = new Specification<Phone>() {
            public Predicate toPredicate(Root<Phone> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                if (brand != null && price != null){
                    Predicate pPrice;
                    if (price == 5000.00){
                        pPrice = criteriaBuilder.ge(root.get("pPrice").as(double.class), price);
                    }else {
                        pPrice = criteriaBuilder.le(root.get("pPrice").as(double.class), price);
                    }
                    Predicate predicate = criteriaBuilder.and(criteriaBuilder.equal(root.get("phoneBrand").get("pbName").as(String.class), brand),pPrice);
                    return predicate;
                }else if (brand != null){
                    Predicate pbName = criteriaBuilder.equal(root.get("phoneBrand").get("pbName").as(String.class), brand);
                    return pbName;
                }else if (price != null){
                    Predicate pPrice;
                    if (price == 5000.00){
                         pPrice = criteriaBuilder.ge(root.get("pPrice").as(double.class), price);
                    }else {
                        pPrice = criteriaBuilder.le(root.get("pPrice").as(double.class), price);
                    }
                    return pPrice;
                }
                return null;
            }
        };
        return phoneRepository.findAll(specification, pageRequest);
    }

    public Map<String, Object> getPhoneById(Integer id) {
        List<Evaluate> evaluates =  evaluateRepository.findByIndent_Phone_pId(id);
        Phone phone = phoneRepository.findById(id).get();
        Map<String,Object> map = new HashMap<>();
        map.put("phone",phone);
        map.put("evaluates",evaluates);
        return map;
    }

    public List<Map<String, Object>> getEcharts() {
      return phoneRepository.getEcharts();
    }


    public void alipay(Phone phone) {
        phoneRepository.save(phone);
    }
}
